Coverage Report

Created: 2021-08-28 18:14

D:\git\skunkworks\herald-for-cpp\herald\src\datatype\windows\sha256.cpp
Line
Count
Source (jump to first uncovered line)
1
//  Copyright 2021 Herald Contributors
2
//  SPDX-License-Identifier: Apache-2.0
3
//
4
5
#include "herald/datatype/sha256.h"
6
7
#include "herald/datatype/data.h"
8
9
// Windows specific libraries
10
#include <windows.h>
11
#include <stdio.h>
12
#include <bcrypt.h>
13
14
namespace herald {
15
namespace datatype {
16
17
18
24
#define NT_SUCCESS(Status)          (((NTSTATUS)(Status)) >= 0)
19
20
4
#define STATUS_UNSUCCESSFUL         ((NTSTATUS)0xC0000001L)
21
22
23
SHA256::SHA256() noexcept
24
4
{
25
4
  ;
26
4
}
27
28
4
SHA256::~SHA256() noexcept = default;
29
30
31
Data
32
4
SHA256::digest(const Data& with) noexcept {
33
4
  // from sample for CNG: https://docs.microsoft.com/en-us/windows/win32/seccng/creating-a-hash-with-cng
34
4
  BCRYPT_ALG_HANDLE       hAlg            = NULL;
35
4
  BCRYPT_HASH_HANDLE      hHash           = NULL;
36
4
  NTSTATUS                status          = STATUS_UNSUCCESSFUL;
37
4
  DWORD                   cbData          = 0,
38
4
                          cbHash          = 0,
39
4
                          cbHashObject    = 0;
40
4
  PBYTE                   message         = NULL;
41
4
  PBYTE                   pbHashObject    = NULL;
42
4
  PBYTE                   pbHash          = NULL;
43
4
  //Data withOppositeEndianness = with.reversed();
44
4
45
4
  Data result;
46
4
47
4
  //open an algorithm handle
48
4
  if(!NT_SUCCESS(status = BCryptOpenAlgorithmProvider(
49
4
                                              &hAlg,
50
4
                                              BCRYPT_SHA256_ALGORITHM,
51
4
                                              NULL,
52
4
                                              0))) // or BCRYPT_HASH_REUSABLE_FLAG
53
4
  {
54
0
      wprintf(L"**** Error 0x%x returned by BCryptOpenAlgorithmProvider\n", status);
55
0
      goto Cleanup;
56
0
  }
57
4
58
4
  //calculate the size of the buffer to hold the hash object
59
4
  if(!NT_SUCCESS(status = BCryptGetProperty(
60
4
                                      hAlg, 
61
4
                                      BCRYPT_OBJECT_LENGTH, 
62
4
                                      (PBYTE)&cbHashObject, 
63
4
                                      sizeof(DWORD), 
64
4
                                      &cbData, /* result length */
65
4
                                      0)))
66
4
  {
67
0
      wprintf(L"**** Error 0x%x returned by BCryptGetProperty\n", status);
68
0
      goto Cleanup;
69
0
  }
70
4
71
4
  //allocate the hash object on the heap
72
4
  pbHashObject = (PBYTE)HeapAlloc (GetProcessHeap (), 0, cbHashObject);
73
4
  if(NULL == pbHashObject)
74
0
  {
75
0
      wprintf(L"**** memory allocation failed\n");
76
0
      goto Cleanup;
77
0
  }
78
4
79
4
  //calculate the length of the hash
80
4
  if(!NT_SUCCESS(status = BCryptGetProperty(
81
4
                                      hAlg, 
82
4
                                      BCRYPT_HASH_LENGTH, 
83
4
                                      (PBYTE)&cbHash, 
84
4
                                      sizeof(DWORD), 
85
4
                                      &cbData, 
86
4
                                      0)))
87
4
  {
88
0
      wprintf(L"**** Error 0x%x returned by BCryptGetProperty\n", status);
89
0
      goto Cleanup;
90
0
  }
91
4
92
4
  //allocate the hash buffer on the heap
93
4
  pbHash = (PBYTE)HeapAlloc (GetProcessHeap (), 0, cbHash);
94
4
  if(NULL == pbHash)
95
0
  {
96
0
      wprintf(L"**** memory allocation failed\n");
97
0
      goto Cleanup;
98
0
  }
99
4
100
4
  //create a hash
101
4
  if(!NT_SUCCESS(status = BCryptCreateHash(
102
4
                                      hAlg, 
103
4
                                      &hHash, 
104
4
                                      pbHashObject, 
105
4
                                      cbHashObject, 
106
4
                                      NULL, 
107
4
                                      0, 
108
4
                                      0)))
109
4
  {
110
0
      wprintf(L"**** Error 0x%x returned by BCryptCreateHash\n", status);
111
0
      goto Cleanup;
112
0
  }
113
4
  
114
4
  // copy over data
115
4
  message = (PBYTE)HeapAlloc (GetProcessHeap (), 0, with.size());
116
48
  for (std::size_t i = 0;i < with.size();
++i44
) {
117
44
    message[i] = BYTE(with.at(i));
118
44
  }
119
4
120
4
  //hash some data
121
4
  if(!NT_SUCCESS(status = BCryptHashData(
122
4
                                      hHash,
123
4
                                      message,
124
4
                                      sizeof(message),
125
4
                                      0)))
126
4
  {
127
0
      wprintf(L"**** Error 0x%x returned by BCryptHashData\n", status);
128
0
      goto Cleanup;
129
0
  }
130
4
  
131
4
  //close the hash
132
4
  if(!NT_SUCCESS(status = BCryptFinishHash(
133
4
                                      hHash, 
134
4
                                      pbHash, 
135
4
                                      cbHash, 
136
4
                                      0)))
137
4
  {
138
0
      wprintf(L"**** Error 0x%x returned by BCryptFinishHash\n", status);
139
0
      goto Cleanup;
140
0
  }
141
4
142
4
  //wprintf(L"Success!\n");
143
4
144
4
  result = Data(pbHash,cbHash);
145
4
146
4
147
4
Cleanup:
148
4
149
4
  if(hAlg)
150
4
  {
151
4
      BCryptCloseAlgorithmProvider(hAlg,0);
152
4
  }
153
4
154
4
  if (hHash)    
155
4
  {
156
4
      BCryptDestroyHash(hHash);
157
4
  }
158
4
159
4
  if(pbHashObject)
160
4
  {
161
4
      HeapFree(GetProcessHeap(), 0, pbHashObject);
162
4
  }
163
4
164
4
  if(pbHash)
165
4
  {
166
4
      HeapFree(GetProcessHeap(), 0, pbHash);
167
4
  }
168
4
169
4
  return result;
170
4
}
171
172
// Initialise to all zeros
173
void
174
0
SHA256::reset() noexcept {
175
0
176
0
}
177
178
179
}
180
}